﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Text.RegularExpressions;
using Pixysoft.RTF.Core;


namespace Pixysoft.RTF
{
    public abstract class RtfBuilderBase : IDisposable
    {
        private RtfColorTable colorTable;
        private RtfFontTable fontTable;


        protected int _firstLineIndent;
        protected int _lineIndent;
        protected StringFormat _sf;
        protected bool _unwrapped;


        protected RtfBuilderBase(RtfFont defaultFont, float defaultFontSize)
        {
            fontTable = new RtfFontTable(defaultFont, defaultFontSize);
            colorTable = new RtfColorTable();

            this._sf = (StringFormat)StringFormat.GenericDefault.Clone();
            this._sf.FormatFlags = StringFormatFlags.NoWrap;
            this._sf.Trimming = StringTrimming.Word;
        }

        ~RtfBuilderBase()
        {
            this.Dispose(false);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                GC.SuppressFinalize(this);
            }
        }
        protected abstract void AppendInternal(string value);
        protected abstract void AppendLevelInternal(int level);
        protected abstract void AppendLineInternal(string value);
        protected abstract void AppendLineInternal();
        protected abstract void AppendPageInternal();
        protected abstract void AppendParaInternal();
        protected abstract void AppendRTFInternal(string rtf);
        protected abstract IEnumerable<RtfBuilderBase> EnumerateCellsInternal(RTFRowDefinition rowDefinition, RTFCellDefinition[] cellDefinitions);
        public abstract IDisposable FormatLock();
        protected abstract void InsertImageInternal(Image image);
        protected abstract int LengthInternal();
        protected abstract void ResetInternal();




        public RtfBuilderBase Append(string value)
        {
            this.AppendInternal(value);
            return this;
        }
        public RtfBuilderBase Append(char[] value)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(value);
            return Append(sb.ToString());
        }
        public RtfBuilderBase Append(short value)
        {
            return Append(value.ToString());
        }
        public RtfBuilderBase Append(double value)
        {
            return Append(value.ToString());
        }
        public RtfBuilderBase Append(float value)
        {
            return Append(value.ToString());
        }
        public RtfBuilderBase Append(int value)
        {
            return Append(value.ToString());
        }
        public RtfBuilderBase Append(string value, int startIndex, int count)
        {
            return Append(value.Substring(startIndex, count));
        }
        public RtfBuilderBase Append(char value, int repeatCount)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(value, repeatCount);
            return Append(sb.ToString());
        }
        public RtfBuilderBase Append(long value)
        {
            return Append(value.ToString());
        }
        public RtfBuilderBase Append(object value)
        {
            return Append(value.ToString());
        }
        public RtfBuilderBase Append(bool value)
        {
            return Append(value.ToString());
        }
        public RtfBuilderBase Append(byte value)
        {
            return Append(value.ToString());
        }
        public RtfBuilderBase Append(decimal value)
        {
            return Append(value.ToString());
        }
        public RtfBuilderBase Append(char value)
        {
            return Append(value.ToString());
        }
        public RtfBuilderBase AppendFormat(string format, object arg0)
        {
            string formated = string.Format(format, arg0);
            return Append(formated);
        }
        public RtfBuilderBase AppendFormat(string format, params object[] args)
        {
            string formated = string.Format(format, args);
            return Append(formated);
        }
        public RtfBuilderBase AppendFormat(IFormatProvider provider, string format, params object[] args)
        {
            string formated = string.Format(provider, format, args);
            return Append(formated);
        }
        public RtfBuilderBase AppendFormat(string format, object arg0, object arg1)
        {
            string formated = string.Format(format, arg0, arg1);
            return Append(formated);
        }
        public RtfBuilderBase AppendFormat(string format, object arg0, object arg1, object arg2)
        {
            string formated = string.Format(format, arg0, arg1, arg2);
            return Append(formated);
        }
        public RtfBuilderBase AppendLevel(int level)
        {
            this.AppendLevelInternal(level);
            return this;
        }
        public RtfBuilderBase AppendLine(string value)
        {
            this.AppendLineInternal(value);
            return this;
        }
        public RtfBuilderBase AppendLine()
        {
            this.AppendLineInternal();
            return this;
        }
        public RtfBuilderBase AppendLineFormat(string format, object arg0)
        {
            string formated = string.Format(format, arg0);
            return this.AppendLine(formated);
        }
        public RtfBuilderBase AppendLineFormat(string format, params object[] args)
        {
            string formated = string.Format(format, args);
            return this.AppendLine(formated);
        }
        public RtfBuilderBase AppendLineFormat(string format, object arg0, object arg1, object arg2)
        {
            string formated = string.Format(format, arg0, arg1, arg2);
            return this.AppendLine(formated);
        }




        public RtfBuilderBase AppendPage()
        {
            this.AppendPageInternal();
            return this;
        }

        public RtfBuilderBase AppendPara()
        {
            this.AppendParaInternal();
            return this;
        }

        public RtfBuilderBase AppendRTF(string rtf)
        {
            this.AppendRTFInternal(rtf);
            return this;
        }

        public RtfBuilderBase AppendRTFDocument(string rtf)
        {
            if (!string.IsNullOrEmpty(rtf))
            {
                if (rtf.IndexOf("viewkind4") > 0)
                {
                    try
                    {
                        string rtfc = RtfUtility.GetColoursFromRtf(this.colorTable, rtf);
                        string rtff = RtfUtility.GetFontsFromRtf(this.fontTable, rtfc);
                        string texttoadd = RtfUtility.GetConcentratedText(rtff);
                        this.AppendRTF(texttoadd);
                    }
                    catch (ArgumentException ex)
                    {
                        this.AppendLine("RTF Document ERROR:");
                        this.AppendLine(ex.Message);
                    }
                }
            }
            return this;
        }




        public RtfBuilderBase ForeColor(KnownColor color)
        {
            this.colorTable.ForeColor = Color.FromKnownColor(color);
            return this;
        }

        public RtfBuilderBase ForeColor(Color color)
        {
            this.colorTable.ForeColor = color;
            return this;
        }

        public RtfBuilderBase ForeColor(int index)
        {
            colorTable.SetForeColor(index);
            return this;
        }

        public RtfBuilderBase BackColor(KnownColor color)
        {
            return this.BackColor(Color.FromKnownColor(color));
        }

        public RtfBuilderBase BackColor(Color color)
        {
            this.colorTable.BackColor = color;
            return this;
        }



        public RtfBuilderBase Font(RtfFont font)
        {
            fontTable.SetFont(font);
            return this;
        }

        public RtfBuilderBase Font(int index)
        {
            fontTable.SetFont(index);
            return this;
        }

        public RtfBuilderBase FontSize(float fontSize)
        {
            fontTable.FontSize = fontSize;
            return this;
        }

        public RtfBuilderBase FontStyle(FontStyle fontStyle)
        {
            fontTable.FontStyle = fontStyle;
            return this;
        }

        public RtfBuilderBase FontStyleNOT(FontStyle fontStyle)
        {
            if ((fontTable.FontStyle & fontStyle) == fontStyle)
            {
                fontTable.FontStyle &= ~fontStyle;
            }
            return this;
        }

        public RtfBuilderBase FontStyleOR(FontStyle fontStyle)
        {
            fontTable.FontStyle |= fontStyle;
            return this;
        }




        public IEnumerable<RtfBuilderBase> EnumerateCells(RTFRowDefinition rowDefinition, RTFCellDefinition[] cellDefinitions)
        {
            return this.EnumerateCellsInternal(rowDefinition, cellDefinitions);
        }





        public RtfBuilderBase InsertImage(Image image)
        {
            this.InsertImageInternal(image);
            return this;
        }



        public RtfBuilderBase LineIndent(int indent)
        {
            this._lineIndent = indent;
            return this;
        }

        public RtfBuilderBase LineIndentFirst(int indent)
        {
            this._firstLineIndent = indent;
            return this;
        }


        public RtfBuilderBase PrependLineFormatIf(string format, ref bool appended, object arg0)
        {
            string formated = string.Format(format, arg0);
            return this.PrependLineIf(formated, ref appended);
        }

        public RtfBuilderBase PrependLineFormatIf(string format, ref bool appended, params object[] args)
        {
            string formated = string.Format(format, args);
            return this.PrependLineIf(formated, ref appended);
        }

        public RtfBuilderBase PrependLineFormatIf(string format, ref bool appended, object arg0, object arg1, object arg2)
        {
            string formated = string.Format(format, arg0, arg1, arg2);
            return this.PrependLineIf(formated, ref appended);
        }

        public RtfBuilderBase PrependLineIf(ref bool appended)
        {
            if (appended)
            {
                this.AppendLine();
            }
            appended = true;
            return this;
        }

        public RtfBuilderBase PrependLineIf(string value, ref bool appended)
        {
            if (appended)
            {
                this.AppendLine();
                Append(value);
            }
            else
            {
                Append(value);
            }
            appended = true;
            return this;
        }




        public RtfBuilderBase Alignment(StringAlignment alignment)
        {
            this._sf.Alignment = alignment;
            return this;
        }

        public void Clear()
        {
        }

        public RtfBuilderBase Reset()
        {
            this.ResetInternal();

            return this;
        }

        public void Dispose()
        {
            this.Dispose(true);
        }

        public int Length
        {
            get { return this.LengthInternal(); }
        }

        public IRtfColorTable ColorTable
        {
            get
            {
                return this.colorTable;
            }
        }

        public IRtfFontTable FontTable
        {
            get
            {
                return this.fontTable;
            }
        }


    }
}